/*******************************************************************************
* File Name    : ymodem.c
* Description  : mbootload的ymodem协议相关文件
* Data         : 2019-08-02  Friday
* Author       : 
*******************************************************************************/
#include "boot_drv.h"
#include "ymodem.h"
#include "string.h"
unsigned char file_name[FILE_NAME_LENGTH];
//用户程序Flash偏移
unsigned long FlashDestination =0;
unsigned long EraseCounter = 0x0;
unsigned long NbrOfPage = 0;
int FLASHStatus;
unsigned long *RamSource;


/**
  * @brief   整形数据转到字符串
  * @param  intnum: 数据
  *            str：转换为的字符串
  * @retval None.
  */
void Int2Str(unsigned char *str, long intnum)
{
    long i, Div = 1000000000, j = 0, Status = 0;

    for (i = 0; i < 10; i++)
    {
        str[j++] = (intnum / Div) + 48;

        intnum = intnum % Div;
        Div /= 10;
        if ((str[j - 1] == '0') & (Status == 0))
        {
            j = 0;
        }
        else
        {
            Status++;
        }
    }
}
/**
  * @brief  字符串转到数据
  * @param  inputstr: 需转换的字符串
  *           intnum：转好的数据
  * @retval 1：正确
  *         0：错误
  */
long Str2Int(unsigned char *inputstr, long *intnum)
{
    long i = 0, res = 0;
    long val = 0;

    if (inputstr[0] == '0' && (inputstr[1] == 'x' || inputstr[1] == 'X'))
    {
        if (inputstr[2] == '\0')
        {
            return 0;
        }
        for (i = 2; i < 11; i++)
        {
            if (inputstr[i] == '\0')
            {
                *intnum = val;
                //返回1
                res = 1;
                break;
            }
            if (ISVALIDHEX(inputstr[i]))
            {
                val = (val << 4) + CONVERTHEX(inputstr[i]);
            }
            else
            {
                //无效输入返回0
                res = 0;
                break;
            }
        }

        if (i >= 11)
        {
            res = 0;
        }
    }
    else //最多10为2输入
    {
        for (i = 0; i < 11; i++)
        {
            if (inputstr[i] == '\0')
            {
                *intnum = val;
                //返回1
                res = 1;
                break;
            }
            else if ((inputstr[i] == 'k' || inputstr[i] == 'K') && (i > 0))
            {
                val = val << 10;
                *intnum = val;
                res = 1;
                break;
            }
            else if ((inputstr[i] == 'm' || inputstr[i] == 'M') && (i > 0))
            {
                val = val << 20;
                *intnum = val;
                res = 1;
                break;
            }
            else if (ISVALIDDEC(inputstr[i]))
            {
                val = val * 10 + CONVERTDEC(inputstr[i]);
            }
            else
            {
                //无效输入返回0
                res = 0;
                break;
            }
        }
        //超过10位无效，返回0
        if (i >= 11)
        {
            res = 0;
        }
    }

    return res;
}

/**
  * @brief   从发送端接收一个数据包
  * @param  data ：数据指针
  *         length：长度
  *         timeout ：超时时间
  * @retval 0: 正常返回
  *        -1: 超时或者数据包错误
  *         1: 用户取消
  */
static long Receive_Packet(unsigned char *data, long *length, unsigned long timeout)
{
    unsigned int i, packet_size;
    unsigned char c=0;
    *length = 0;
    if (mbl_recv_byte(&c, timeout) != 0)
    {
        return -1;
    }
    switch (c)
    {
    case SOH:
        packet_size = PACKET_SIZE;
        break;
    case STX:
        packet_size = PACKET_1K_SIZE;
        break;
    case EOT:
        return 0;
    case CA:
        if ((mbl_recv_byte(&c, timeout) == 0) && (c == CA))
        {
            *length = -1;
            return 0;
        }
        else
        {
            return -1;
        }
    case ABORT1:
    case ABORT2:
        return 1;
    default:
        return -1;
    }
    *data = c;
    for (i = 1; i < (packet_size + PACKET_OVERHEAD); i++)
    {
        if (mbl_recv_byte(data + i, timeout) != 0)
        {
            return -1;
        }
    }
    if (data[PACKET_SEQNO_INDEX] != ((data[PACKET_SEQNO_COMP_INDEX] ^ 0xff) & 0xff))
    {
        return -1;
    }
    *length = packet_size;
    return 0;
}
/**
  * @brief   通过 ymodem协议接收一个文件
  * @param  buf: 首地址指针
  * @retval 文件长度
  */
__align(4) unsigned char	packet_d[PACKET_1K_SIZE + PACKET_OVERHEAD + 1];
unsigned char *packet_data = packet_d+1;
long Ymodem_Receive(unsigned long appAdr)
{
    unsigned char file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr;
    long i, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;
		FlashDestination=MBL_APP_WR_ADR;
    for (session_done = 0, errors = 0, session_begin = 0;;)
    {
        for (packets_received = 0, file_done = 0,buf_ptr=packet_data;;)
        {
            switch (Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT))
            {
            case 0:
                errors = 0;
                switch (packet_length)
                {
                    //发送端终止
                case -1:
                    mbl_send_byte(ACK);
                    return MBL_YMODEM_ABORTED_ERROR;
                    //结束传输
                case 0:
                    mbl_send_byte(ACK);
                    file_done = 1;
                    break;
                    //正常的数据包
                default:
                    if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff))
                    {
                      mbl_send_byte(NAK);
                    }
                    else
                    {
											if (packets_received == 0)
											{
												//文件名数据包
												if (packet_data[PACKET_HEADER] != 0)
												{
													//文件名数据包有效数据区域
													for (i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH);)
													{
														file_name[i++] = *file_ptr++;
													}
													file_name[i++] = '\0';
													for (i = 0, file_ptr++; (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH);)
													{
														file_size[i++] = *file_ptr++;
													}
													file_size[i++] = '\0';
													Str2Int(file_size, &size);

													//测试数据包是否过大
													if (size > (MBL_IMAGE_FREE_SIZE - 1))
													{
														//结束
														mbl_send_byte(CA);
														mbl_send_byte(CA);
														return -1;
													}
								
													if(mbl_flash_erase(MBL_APP_WR_ADR,size)==-1)
													{
														//结束
														mbl_send_byte(CA);
														mbl_send_byte(CA);
														return MBL_FLASH_ERASE_ERROR;
													}
													else
													{
														mbl_send_byte(ACK);
														mbl_send_byte(CRC16);
													}
												}
												//文件名数据包空，结束传输
												else
												{
													mbl_send_byte(ACK);
													file_done = 1;
													session_done = 1;
													break;
												}
										}
										//数据包
										else
										{
											RamSource = (unsigned long *)(buf_ptr+PACKET_HEADER);
											//把接收到的数据编写到Flash中
											if (mbl_flash_write_word(FlashDestination, RamSource,packet_length/4,MBL_APP_WR_ADR)<0)
											{
												//结束
												mbl_send_byte(CA);
												mbl_send_byte(CA);
												return MBL_FLASH_WRITE_ERROR;
											}
											FlashDestination += packet_length;
											mbl_send_byte(ACK);
										}
										packets_received++;
										session_begin = 1;
									}
                }
                break;
            case 1:
                mbl_send_byte(CA);
                mbl_send_byte(CA);
                return MBL_YMODEM_ABORTED_USER;
            default:
                if (session_begin > 0)
                {
									errors++;
                }
                if (errors > MAX_ERRORS)
                {
									mbl_send_byte(CA);
									mbl_send_byte(CA);
									return 0;
                }
                mbl_send_byte(CRC16);
                break;
            }
            if (file_done != 0)
            {
							break;
            }
        }
        if (session_done != 0)
        {
            break;
        }
    }
    return (long)size;
}
/**
  * @brief   通过 ymodem协议检测响应
  * @param  c: 测试字符
  * @retval none
  */
	/*
long Ymodem_CheckResponse(unsigned char c)
{
    return 0;
}
*/
/**
  * @brief   准备第一个数据包
  * @param  data：数据包
  *         fileName ：文件名
  *         length ：长度
  * @retval none
  */
	/*
void Ymodem_PrepareIntialPacket(unsigned char *data, const unsigned char *fileName, unsigned long *length)
{
    unsigned int i, j;
    unsigned char file_ptr[10];

    //制作头3个数据包
    data[0] = SOH;
    data[1] = 0x00;
    data[2] = 0xff;
    //文件名数据包有效数据
    for (i = 0; (fileName[i] != '\0') && (i < FILE_NAME_LENGTH); i++)
    {
        data[i + PACKET_HEADER] = fileName[i];
    }

    data[i + PACKET_HEADER] = 0x00;

    Int2Str(file_ptr, *length);
    for (j = 0, i = i + PACKET_HEADER + 1; file_ptr[j] != '\0';)
    {
        data[i++] = file_ptr[j++];
    }

    for (j = i; j < PACKET_SIZE + PACKET_HEADER; j++)
    {
        data[j] = 0;
    }
}
*/
/**
  * @brief   准备数据包
  * @param  SourceBuf：数据源缓冲
  *         data：数据包
  *         pktNo ：数据包编号
  *         sizeBlk ：长度
  * @retval none
  */
	/*
void Ymodem_PreparePacket(unsigned char *SourceBuf, unsigned char *data, unsigned char pktNo, unsigned long sizeBlk)
{
    unsigned int i, size, packetSize;
    unsigned char *file_ptr;

    //制作头3个数据包
    packetSize = sizeBlk >= PACKET_1K_SIZE ? PACKET_1K_SIZE : PACKET_SIZE;
    size = sizeBlk < packetSize ? sizeBlk : packetSize;
    if (packetSize == PACKET_1K_SIZE)
    {
        data[0] = STX;
    }
    else
    {
        data[0] = SOH;
    }
    data[1] = pktNo;
    data[2] = (~pktNo);
    file_ptr = SourceBuf;

    //文件名数据包有效数据
    for (i = PACKET_HEADER; i < size + PACKET_HEADER; i++)
    {
        data[i] = *file_ptr++;
    }
    if (size <= packetSize)
    {
        for (i = size + PACKET_HEADER; i < packetSize + PACKET_HEADER; i++)
        {
            data[i] = 0x1A; //结束
        }
    }
}
*/
/**
  * @brief   更新输入数据的CRC校验
  * @param  crcIn：
  *         byte：
  * @retval CRC校验值
  */
unsigned int UpdateCRC16(unsigned int crcIn, unsigned char byte)
{
	unsigned long crc = crcIn;
	unsigned long in = byte | 0x100;
	do
	{
			crc <<= 1;
			in <<= 1;
			if (in & 0x100)
					++crc;
			if (crc & 0x10000)
					crc ^= 0x1021;
	} while (!(in & 0x10000));
	return crc & 0xffffu;
}
/**
  * @brief   更新输入数据的CRC校验
  * @param  data ：数据
  *         size ：长度
  * @retval CRC校验值
  */
#if defined(MBL_USE_CRC16)
unsigned int Cal_CRC16(const unsigned char *data, unsigned long size)
{
    unsigned long crc = 0;
    const unsigned char *dataEnd = data + size;
    while (data < dataEnd)
        crc = UpdateCRC16(crc, *data++);

    crc = UpdateCRC16(crc, 0);
    crc = UpdateCRC16(crc, 0);
    return crc & 0xffffu;
}
// The table for fast CRC16 calculation 
static const uint8_t crc_hi[] = {
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
    0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
    0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80,
    0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00,
    0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81,
    0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
    0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81,
    0x40
};

static const uint8_t crc_low[] = {
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
    0x05, 0xC5, 0xC4,
    0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB,
    0x0B, 0xC9, 0x09,
    0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE,
    0xDF, 0x1F, 0xDD,
    0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2,
    0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
    0x36, 0xF6, 0xF7,
    0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E,
    0xFE, 0xFA, 0x3A,
    0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B,
    0x2A, 0xEA, 0xEE,
    0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27,
    0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
    0x63, 0xA3, 0xA2,
    0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD,
    0x6D, 0xAF, 0x6F,
    0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8,
    0xB9, 0x79, 0xBB,
    0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4,
    0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
    0x50, 0x90, 0x91,
    0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94,
    0x54, 0x9C, 0x5C,
    0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59,
    0x58, 0x98, 0x88,
    0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D,
    0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
    0x41, 0x81, 0x80,
    0x40
};

// Calculate buffer checksum using tables 
// The checksum CRC16 algorithm is specific
// for Modbus standard and uses polynomial value = 0xA001
static uint16_t get_buffer_crc16( uint8_t * frame_ptr, uint16_t length )
{
    while( frame_ptr == NULL);

    uint8_t crc_hi_byte = 0xFF;
    uint8_t crc_low_byte = 0xFF;
    int index;

    while ( length-- )
    {
        index = crc_low_byte ^ *(frame_ptr++);
        crc_low_byte = crc_hi_byte ^ crc_hi[index];
        crc_hi_byte = crc_low[index];
    }
    return ((crc_hi_byte << 8) | crc_low_byte);
}

#endif
/**
  * @brief  计算YModem数据包的总大小
  * @param  data ：数据
  *         size ：长度
  * @retval 数据包的总大小
  */
/*
unsigned char CalChecksum(const unsigned char *data, unsigned long size)
{
    unsigned long sum = 0;
    const unsigned char *dataEnd = data + size;
    while (data < dataEnd)
        sum += *data++;
    return sum & 0xffu;
}
*/
/**
  * @brief  通过ymodem协议传输一个数据包
  * @param  data ：数据地址指针
  *         length：长度
  * @retval none
  */
/*
void Ymodem_SendPacket(unsigned char *data, unsigned int length)
{
    unsigned int i;
    i = 0;
    while (i < length)
    {
        mbl_send_byte(data[i]);
        i++;
    }
}
*/
/**
  * @brief  通过ymodem协议传输一个文件
  * @param  buf ：数据地址指针
  *         sendFileName ：文件名
  *         sizeFile：文件长度
  * @retval 0：成功
  */
/*
unsigned char Ymodem_Transmit(unsigned char *buf, const unsigned char *sendFileName, unsigned long sizeFile)
{

    unsigned char packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD];
    unsigned char FileName[FILE_NAME_LENGTH];
    unsigned char *buf_ptr, tempCheckSum;
    unsigned int tempCRC, blkNumber;
    unsigned char receivedC[2], CRC16_F = 0, i;
    unsigned long errors, ackReceived, size = 0, pktSize;

    errors = 0;
    ackReceived = 0;
    for (i = 0; i < (FILE_NAME_LENGTH - 1); i++)
    {
        FileName[i] = sendFileName[i];
    }
    CRC16_F = 1;

    //准备第一个数据包
    Ymodem_PrepareIntialPacket(&packet_data[0], FileName, &sizeFile);

    do
    {
        //发送数据包
        Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER);
        //发送CRC校验
        if (CRC16_F)
        {
            tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE);
            mbl_send_byte(tempCRC >> 8);
            mbl_send_byte(tempCRC & 0xFF);
        }
        else
        {
            tempCheckSum = CalChecksum(&packet_data[3], PACKET_SIZE);
            mbl_send_byte(tempCheckSum);
        }

        //等待响应
        if (mbl_recv_byte(&receivedC[0], 10000) == 0)
        {
            if (receivedC[0] == ACK)
            {
                //数据包正确传输
                ackReceived = 1;
            }
        }
        else
        {
            errors++;
        }
    } while (!ackReceived && (errors < 0x0A));

    if (errors >= 0x0A)
    {
        return errors;
    }
    buf_ptr = buf;
    size = sizeFile;
    blkNumber = 0x01;

    //1024字节的数据包发送
    while (size)
    {
        //准备下一个数据包
        Ymodem_PreparePacket(buf_ptr, &packet_data[0], blkNumber, size);
        ackReceived = 0;
        receivedC[0] = 0;
        errors = 0;
        do
        {
            //发送下一个数据包
            if (size >= PACKET_1K_SIZE)
            {
                pktSize = PACKET_1K_SIZE;
            }
            else
            {
                pktSize = PACKET_SIZE;
            }
            Ymodem_SendPacket(packet_data, pktSize + PACKET_HEADER);
            //发送CRC校验
            if (CRC16_F)
            {
                tempCRC = Cal_CRC16(&packet_data[3], pktSize);
                mbl_send_byte(tempCRC >> 8);
                mbl_send_byte(tempCRC & 0xFF);
            }
            else
            {
                tempCheckSum = CalChecksum(&packet_data[3], pktSize);
                mbl_send_byte(tempCheckSum);
            }

            //等待响应
            if ((mbl_recv_byte(&receivedC[0], 100000) == 0) && (receivedC[0] == ACK))
            {
                ackReceived = 1;
                if (size > pktSize)
                {
                    buf_ptr += pktSize;
                    size -= pktSize;
                    if (blkNumber == (FLASH_IMAGE_SIZE / 1024))
                    {
                        return 0xFF; //错误
                    }
                    else
                    {
                        blkNumber++;
                    }
                }
                else
                {
                    buf_ptr += pktSize;
                    size = 0;
                }
            }
            else
            {
                errors++;
            }
        } while (!ackReceived && (errors < 0x0A));
        //如果没响应10次就返回错误
        if (errors >= 0x0A)
        {
            return errors;
        }
    }
    ackReceived = 0;
    receivedC[0] = 0x00;
    errors = 0;
    do
    {
        mbl_send_byte(EOT);
        //发送 (EOT);
        //等待回应
        if ((mbl_recv_byte(&receivedC[0], 10000) == 0) && receivedC[0] == ACK)
        {
            ackReceived = 1;
        }
        else
        {
            errors++;
        }
    } while (!ackReceived && (errors < 0x0A));

    if (errors >= 0x0A)
    {
        return errors;
    }
    //准备最后一个包
    ackReceived = 0;
    receivedC[0] = 0x00;
    errors = 0;

    packet_data[0] = SOH;
    packet_data[1] = 0;
    packet_data[2] = 0xFF;

    for (i = PACKET_HEADER; i < (PACKET_SIZE + PACKET_HEADER); i++)
    {
        packet_data[i] = 0x00;
    }

    do
    {
        //发送数据包
        Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER);
        //发送CRC校验
        tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE);
        mbl_send_byte(tempCRC >> 8);
        mbl_send_byte(tempCRC & 0xFF);

        //等待响应
        if (mbl_recv_byte(&receivedC[0], 10000) == 0)
        {
            if (receivedC[0] == ACK)
            {
                //包传输正确
                ackReceived = 1;
            }
        }
        else
        {
            errors++;
        }

    } while (!ackReceived && (errors < 0x0A));
    //如果没响应10次就返回错误
    if (errors >= 0x0A)
    {
        return errors;
    }

    do
    {
        mbl_send_byte(EOT);
        //发送 (EOT);
        //等待回应
        if ((mbl_recv_byte(&receivedC[0], 10000) == 0) && receivedC[0] == ACK)
        {
            ackReceived = 1;
        }
        else
        {
            errors++;
        }
    } while (!ackReceived && (errors < 0x0A));

    if (errors >= 0x0A)
    {
        return errors;
    }
    return 0; //文件传输成功
}
*/
